package com.czy.lxtFX;

import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

/**
 * 字符串工具
 * @author chenzy
 * @since 2019.12.19
 */
public class StringUtil {
    private StringUtil() {
    }
    /*字符串中是否包含字母*/
    public static boolean containLetters(String str) {
        return Pattern.compile(".*[a-zA-Z]+.*").matcher(str).matches();
    }
    /*字符串中是否包含数字*/
    public static boolean containNum(String str) {
        return Pattern.compile(".*[0-9]+.*").matcher(str).matches();
    }
    /*字符在字符串出现次数*/
    private int getNum(String str,Character c){
        if (StringUtil.isBlankOr(str,c)){
            return 0;
        }
        return (str+(c+1)).split(c.toString()).length-1;
    }
    public static Character[] getArray(String str) {
        if (isBlank(str)) {
            return null;
        }
        var chars = str.toCharArray();
        var result = new Character[chars.length];
        for (var i = 0; i < chars.length; i++) {
            result[i] = chars[i];
        }
        return result;
    }

    public static String replaceALL(String str, String pattern, List<Object> values) {
        if (values == null || values.isEmpty() || isBlank(str)) {
            return str;
        }
        for (Object value : values) {
            str = str.replaceFirst(pattern, value + "");
        }
        return str;
    }


    /*jdk序列化*/
    public static <T> byte[] serializeJDK(T object) {
        try (var byteStrem = new ByteArrayOutputStream();
             var outStrem = new ObjectOutputStream(byteStrem)
        ) {
            outStrem.writeObject(object);
            return byteStrem.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Object derializerJDK(byte[] value) {
        if (value == null || value.length < 1) {
            return null;
        }
        try (var in = new ObjectInputStream(new ByteArrayInputStream(value))) {
            return in.readObject();
        } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * msg中的{}用pars代替
     */
    public static String join(String msg, Object... pars) {
        if (msg == null || !msg.contains("{}") || pars == null || pars.length == 0) {
            return msg;
        }
        for (var par : pars) {
            var temp = par == null ? "" : par.toString();
            if (temp.contains("{}")) {
                /*obj.toString中可能包含{}*/
                temp = temp.replaceAll("\\{}", "");
            }
            msg = msg.replaceFirst("\\{}", temp);
        }
        return msg;
    }

    public static String println(String msg, Object... pars) {
        var result = join(msg, pars);
        System.out.println(result);
        return result;
    }

    public static boolean empty(String str) {
        return (str == null || str.isEmpty());
    }

    public static String replace(String inString, String oldPattern, String newPattern) {
        if (empty(inString) || empty(oldPattern) || newPattern == null) {
            return inString;
        }
        int index = inString.indexOf(oldPattern);
        if (index == -1) {
            // no occurrence -> can return input as-is
            return inString;
        }

        int capacity = inString.length();
        if (newPattern.length() > oldPattern.length()) {
            capacity += 16;
        }
        var sb = new StringBuilder(capacity);

        int pos = 0;  // our position in the old string
        int patLen = oldPattern.length();
        while (index >= 0) {
            sb.append(inString, pos, index);
            sb.append(newPattern);
            pos = index + patLen;
            index = inString.indexOf(oldPattern, pos);
        }

        // append any characters to the right of a match
        sb.append(inString, pos, inString.length());
        return sb.toString();
    }
    /*擦除指定字符*/
    public static String erase(String str,String reg){
        if (isBlank(str)){
            return "";
        }
        return Pattern.compile(reg).matcher(str.strip()).replaceAll("");
    }
    /**
     * 擦除首尾空格，文本内部多个空格转成一个空格
     */
    public static String eraseSpace(String str) {
        if (isBlank(str)){
            return "";
        }
        return Pattern.compile("\\s+").matcher(str.strip()).replaceAll(" ");
    }
    /*擦除文本所有空格*/
    public static String eraseAllSpace(String str) {
        return erase(str,"\\s+");
    }
    /**
     * 擦除中文
     */
    public static String eraseChinese(String str) {
        return erase(str,"[\u4e00-\u9fa5]");
    }

    /**
     * 十进制数转十六进制数
     */
    public static Integer decimal2Hex(Integer num) {
        return Integer.parseInt("ff", num);
    }

    /**
     * 十进制数转十六进制数，不够指定位数就在前面补零。超过位数不截取
     *
     * @param num    十进制数
     * @param digits 位数，转成多少位的十六进制数
     */
    public static String decimal2Hex(Integer num, int digits) {
        return String.format("%0" + digits + "x", num);
    }

    /**
     * 十六进制数转十进制数，不够指定位数就在前面补零。超过位数不截取
     *
     * @param hexStr 十六进制数
     * @param digits 位数，转成多少位的十进制数
     */
    public static String hex2Decimal(String hexStr, int digits) {
        return String.format("%0" + digits + "d", new BigInteger(hexStr, 16), true);
    }

    /**
     * 十六进制数转十进制数，不够指定位数就在前面补零。
     *
     * @param hexStr            十六进制数
     * @param digits            位数，转成多少位的十进制数
     * @param allowExceedDigits 为false且超出长度将返回指定位数的0
     */
    public static String hex2Decimal(String hexStr, int digits, boolean allowExceedDigits) {
        var result = String.format("%0" + digits + "d", new BigInteger(hexStr, 16));
        if (!allowExceedDigits && result.length() > digits) {
            return String.format("%0" + digits + "d", 0);
        }
        return result;
    }

    /**
     * 随机生成6位数(字母加数字)
     */
    public static String random6Num() {
        var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var result = new StringBuilder();
        var random=new Random();
        var length=str.length();
        Stream.iterate(0,i->i+1).limit(6).forEach(i-> result.append(str.charAt(random.nextInt(length))));
        return result.toString();
    }

    /**
     * 都不为空
     */
    public static boolean isNotBlankAnd(Object... objs) {
        return !isBlankOr(objs);
    }

    /**
     * 都不为空
     */
    public static boolean isNotBlankAnd(String... strs) {
        return !isBlankOr(strs);
    }

    public static boolean isNotBlank(Object object) {
        return !isBlank(object);
    }

    public static boolean isNotBlank(String str) {
        return !isBlank(str);
    }

    public static boolean isBlank(Object obj) {
        return obj == null || isBlank(obj.toString());
    }

    public static boolean isBlank(String str) {
        if (str == null) {
            return true;
        }
        return str.isBlank();
    }
    /**
     * 判断参数是否都为空
     */
    public static boolean isBlankAnd(String... strs) {
        if (ListUtil.isEmpty(strs)) {
            return true;
        }
        return Arrays.stream(strs).allMatch(StringUtil::isBlank);
    }
    /**
     * 判断参数是否存在空
     */
    public static boolean isBlankOr(String... strs) {
        if (ListUtil.isEmpty(strs)) {
            return true;
        }
        return Arrays.stream(strs).anyMatch(StringUtil::isBlank);
    }
    public static boolean isBlankAnd(Object... objs) {
        if (ListUtil.isEmpty(objs)) {
            return true;
        }
        return Arrays.stream(objs).allMatch(StringUtil::isBlank);
    }

    public static boolean isBlankOr(Object... objs) {
        if (ListUtil.isEmpty(objs)) {
            return true;
        }
        return Arrays.stream(objs).anyMatch(StringUtil::isBlank);
    }
    /**
     * 判断字符是否是字母(a-z或者A-Z)
     */
    public static Boolean isLetter(Character c) {
        return Character.isLowerCase(c) || Character.isUpperCase(c);
    }

    /**
     * 判断字符是否都是字母(a-z或者A-Z)
     */
    public static Boolean isLetterAnd(Character... cs) {
        if (cs == null) {
            return false;
        }
        return Arrays.stream(cs).allMatch(StringUtil::isLetter);
    }


    /**
     * 转换boolean 1表示true 其他false
     * 字符串true表示true 其他false
     */
    public static Boolean getBoolean(String value) {
        if (StringUtil.isBlank(value)) {
            return false;
        }
        return value.equals("1") || value.toLowerCase().equals("true");
    }

    /**
     * 转换成boolean值 1表示true 其他false
     * 字符串true表示true 其他false
     */
    public static Boolean getBoolean(Object value) {
        return getBoolean(value, false);
    }

    /**
     * 转换成boolean值 1表示true 其他false
     * 字符串true表示true 其他false
     */
    public static Boolean getBoolean(Object value, Boolean defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        return getBoolean(value.toString());
    }


    /**
     * boolean值转int
     * true=》 1 false=》0
     */
    public static Integer getInt(Boolean value) {
        return value ? 1 : 0;
    }


    /**
     * 得到毫秒值
     * 将1000ms转成1000
     */
    public static Long getLongByMS(Object value, Long defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        String temp = value.toString().toLowerCase();
        if (temp.endsWith("ms")) {
            temp=temp.substring(0,temp.length()-2);
        }
        return Long.valueOf(temp);
    }



    public static String getStr(Object value, String defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        return value.toString();
    }


    /**
     * 金额转换
     * 0.22 转换22
     * 即0.22元换成22分
     */
    public static Integer strMoney2Int(String money) {
        if (isBlank(money)) {
            return 0;
        }
        if (!money.contains(".")){
            return Integer.parseInt(money) * 100;
        }
        var ss = money.split("\\.");
        return Integer.valueOf(ss[0]) * 100 + Integer.valueOf(ss[1]);
    }
    public static boolean equalOr(String str, String... compares) {
        if (str==null){
            return false;
        }
        return Arrays.stream(compares).anyMatch(str::equals);
    }
    /**
     * 判断两个对象是否相等
     */
    public static Boolean equal(Object o1, Object o2) {
        if (o1 == null) {
            return o2 == null;
        }
        if (o2 == null) {
            return false;
        }
        if (o1.getClass() == o2.getClass()) {
            return o1.equals(o2);
        }
        return o1.toString().equals(o2.toString());
    }

    /**
     * 字符串首字母大写
     */
    public static String upFirst(String str) {
        if (isBlank(str)) {
            return str;
        }
        // 进行字母的ascii编码前移，效率要高于截取字符串进行转换的操作
        var cs = str.toCharArray();
        if (cs[0] >= 'a' && cs[0] <= 'z') {
            cs[0] -= 32;
            return String.valueOf(cs);
        } else {
            return str;
        }
    }

    /**
     * 字符串首字母小写
     */
    public static String lowFirst(String str) {
        if (isBlank(str)) {
            return str;
        }
        // 进行字母的ascii编码前移，效率要高于截取字符串进行转换的操作
        var cs = str.toCharArray();
        if (cs[0] >= 'A' && cs[0] <= 'Z') {
            cs[0] += 32;
            return String.valueOf(cs);
        } else {
            return str;
        }
    }

    /**
     * 下划线转驼峰
     */
    public static String lineToHump(String str) {
        str = str.toLowerCase();
        var matcher = Pattern.compile("_(\\w)").matcher(str);
        var sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /***
     * 验证字符串是否是指定格式
     * @param str 待验证的字符串
     * @param patternS 正则表达式
     */
    public static boolean matcher(String str, String patternS) {
        return Pattern.compile(patternS).matcher(str).matches();
    }

    /**
     * 验证字符串是否是数字，包括负数，小数
     */
    public static boolean isNumeric(String str) {
        //Pattern pattern = Pattern.compile("^-?[0-9]+"); //这个也行
        return matcher(str, "^-?\\d+(\\.\\d+)?$");
    }

    /**
     * 验证字符串是否是正整数
     */
    public static boolean isPositiveInt(String str) {
        return matcher(str, "^[0-9]*$");
    }

    /*根据正则表达式获取字符串，返回第一次出现的子串，若正则表达式没有出现，则返回""*/
    public static String subStr(String str, String regex) {
        return subStr(str, regex, 1);
    }

    /**
     * 根据正则表达式获取字符串，返回第n次出现的子串，若正则表达式没有出现，则返回""
     */
    public static String subStr(String str, String regex, Integer n) {
        if (isBlankOr(str, regex)) {
            return "";
        }
        Matcher mat = Pattern.compile(regex).matcher(str);
        Integer index = 0;
        while (mat.find()) {
            index++;
            //第N次出现位置
            if (index.equals(n)) {
                return str.substring(mat.start(), mat.end());
            }
        }
        return "";
    }


    public static void main(String[] args) {
    }


    public static String concat(Object... msgs) {
        if (ListUtil.isEmpty(msgs)) {
            return "";
        }
        StringBuilder result=new StringBuilder();
        Arrays.stream(msgs).filter(Objects::nonNull).forEach(result::append);
        return result.toString();
    }

    /**
     * 字符串多倍复制，以参数三为分隔符
     */
    public static String copy(String str, int multiples, String separator) {
        if (StringUtil.isBlank(str) || multiples == 0) {
            return "";
        }
        if (isBlank(separator)) {
            return str.repeat(multiples);
        }
        StringBuilder result = new StringBuilder(str);
        for (int i = 1; i < multiples; i++) {
            result.append(separator).append(str);
        }
        return result.toString();
    }

}
